As @InnovArul said, the manipulation of data won’t be traced and thus might lead to a wrong result.
Here is a simple example demonstrating this issue.
In the first part of the code, we just calculate the loss for our operations and apply the gradient on w.
We expect values of [[17., 17.]] after the update.
In the second example, I’ve manipulated the underlying data of w after the gradient calculation.
Autograd did not trace this manipulation and the gradients for the original w are now applied on the manipulated w.

# Standard approach
x = torch.ones(1, 2)
w = torch.ones(2, 1, requires_grad=True)
target = torch.full((1,), 10.)
optimizer = torch.optim.SGD([w], lr=1.)

output = x.mm(w)
loss = (output - target)**2
loss.backward()
print(w.grad)
> tensor([[-16.],
          [-16.]])
optimizer.step()
print(w)
> tensor([[ 17.],
          [ 17.]])

# Now manipulate the underlying data
w = torch.ones(2, 1, requires_grad=True)
optimizer = torch.optim.SGD([w], lr=1.)

output = x.mm(w)
loss = (output - target)**2
loss.backward()
print(w.grad)
> tensor([[-16.],
          [-16.]])
w.data = torch.full((2, 1), -100.)
optimizer.step()
print(w)
> tensor([[-84.],
          [-84.]])