Ho ok,
The confusion is that y_ = xxx in you second example is not an inplace change of the tensor ! a[0] is an inplace change of the list, but if you were doing a = 2 it would not change the original list. It’s just reassigning the variable named “a” or “y_” to a different python object. If you were doing y_.copy_(xxx) or y[0] = xxx then the change would be visible as well.
The code below cover all cases for list and tensors.
You will see that in each case, inplace modifications will modify what was given as input.
import torch

def inplace_change(a):
    print("doing inplace change")
    a[0] = 2
    return a
def inplace_tensor_change(a):
    print("doing inplace change on a.data")
    # This is bad, never use .data in proper code !
    a.data = torch.rand(5)
    return a
def out_of_place_change(a):
    print("doing out of place change")
    a = 2
    return a

a=[[1, 2, 3]]
print("working with ", a)
print("Giving a[0]")
print(inplace_change(a[0]))
print(a)
print("")
a=[[1, 2, 3]]
print("working with ", a)
print("Giving a")
print(inplace_change(a))
print(a)
print("")
a=torch.Tensor([1, 2, 3])
print("working with ", a)
print("Giving a")
print(inplace_change(a))
print(a)
print("")
a=torch.Tensor([1, 2, 3])
print("working with ", a)
print("Giving a")
print(inplace_tensor_change(a))
print(a)
print("")
a=torch.Tensor([1, 2, 3])
print("working with ", a)
print("Giving a.data")
print(inplace_change(a.data))
print(a)
print("")


a=[[1, 2, 3]]
print("working with ", a)
print("Giving a[0]")
print(out_of_place_change(a[0]))
print(a)
print("")
a=[[1, 2, 3]]
print("working with ", a)
print("Giving a")
print(out_of_place_change(a))
print(a)
print("")
a=torch.Tensor([1, 2, 3])
print("working with ", a)
print("Giving a")
print(out_of_place_change(a))
print(a)
print("")
a=torch.Tensor([1, 2, 3])
print("working with ", a)
print("Giving a.data")
print(out_of_place_change(a.data))
print(a)
print("")