x=torch.tensor(10.).requires_grad_()

w=torch.tensor([0.]).requires_grad_()
z=torch.empty(1)
for i in range(5):
    #w.require_grad=True
    w=x*2+i
    

w.backward() #works
w.backward() # grads freed, does not work


why this does not work?
x=torch.tensor(10.).requires_grad_()

w=torch.tensor([0.]).requires_grad_()
z=torch.empty(1)
for i in range(5):
    #w.require_grad=True
    w=(x-1)-i

w.backward() #works
w.backward() # works

Why the above works?
x=torch.tensor(10.).requires_grad_()

w=torch.tensor([0.]).requires_grad_()
z=torch.empty(1)
for i in range(5):
    #w.require_grad=True
    w=(x/1)-i

w.backward() #works
w.backward() # grads freed, does not work

Why above one does not work?
Does pytorch treat +/- differently than * or / because of how derivatives are calculated for them? As for +/- upward gradient is just distributed, but  for  * and / there are actually different ways to calculate derivative?
So, pytorch create graphs to determine gradients, simple as that. If network only distributes gradient, then there are no intermediate operations to be freed?