The .grad field are allocated lazily. So if they are None, you can do w_.grad = grads[0] I think.
When they already exist, you don’t want this copy to be tracked by the autograd actualy so you should do:
grads = torch.autograd.grad(loss, [w_, b_])
with torch.no_grad():
    w_.grad.fill_(grads[0])
    b_.grad.fill_(grads[1])
optimizer.step()