Thinking about it, w_.grad = grads[0] is not a great idea either  You should do w_.grad = grads[0].detach().
Otherwise, same as if you were not using torch.no_grad() you would create a memory leak if grads.requires_grad is True.
Basically, a computational graph is kept in memory as long as it could be used for a backward.
For example if you use a net to compute a scalar loss. Then as long as you have your loss that exist, all the computational graph and intermediary results associated will stay in memory.
If you do w_.grad.fill_(grads[0]), then w_.grad becomes reponsible for the whole graph. And since w_.grad is never deleted, the graph will remain forever.
In your case, grads should not require gradient as you don’t pass the corresponding flags to autograd.grad.
In general, I like it as it makes the code more readable (you are sure this block is not part of your model) and future proof: if one day you change something that makes grads require grad, it will still work and not create a memory leak.