Your title says "...without reassigning to itself...": Because A is a reference type, Select() doesn't create copies of the items in the source collection. Your lambda gets each actual object in turn. When it sets x.B = 0, it's acting on the original item that's still in the collection.
The more interesting question is why the arr1 and the arr2 code behave differently.
Let's take a look at what Select() returns:
var z = arr2.Select(x => { x.B = 0; return x; });
arr2.ToList();
Set a breakpoint on the second line there, and we find that this is type of z; this is the thing that is returned by arr2.Select(x => { x.B = 0; return x; }). It's the same type of object you're calling ToList() on in the arr1 line:
System.Linq.Enumerable.SelectListIterator<ConsoleApp3.A, ConsoleApp3.A>
Select() doesn't do much. It returns an object that's prepared to iterate over each item in arr2 in turn, set the B property of each item, and then return each item in turn.
It's ready to do that. But it hasn't done it, and it won't do it until you ask it to (lazy evaluation, as you suggest). Let's try this:
var a = z.First();
That tells the SelectListIterator to evaluate the Select() lambda for just the first item in arr2. That's all it does. Now the first item in arr2 has B == 0, but the rest don't, because you didn't touch them yet. So let's touch all of them:
var b = z.ToList();
Now the ToList() call will force the SelectListIterator to go through and execute your Select() lambda expression for every item in arr2. You did that right away for arr1, which is why B was zero for every item in arr1. You never did it for arr2 in your code at all. The thing that does the work is not the Select(), but the object returned by Select(). For arr2, you discarded that object without enumerating it, so it never did the work.
And we now understand that arr2.ToList() didn't do anything: In the case of arr1, t was the act of calling ToList() on the result of the Select() that applied the Select()'s changes to arr1. If you had called arr1.ToList(); instead, that would have had no effect either. It would just create an exact copy of arr1, and if you didn't assign that to anything, it would just be discarded.
All of this is one reason why we never put side effects in LINQ expressions: You create effects which are baffling even in a minimal, highly simplified example created for a StackOverflow question. You don't need that in production code.
Another reason is we never need to.