maybe try using:
# Gradient-Penalty hook
def gradient_penelty(
    critic, 
    real: torch.Tensor, 
    fake: torch.Tensor,
    gamma: float = 1.
):
    # randomize alpha, so every time we see a different points
    # on the line connecting real and fake samples.
    alpha = torch.rand(1, 1).to(device)
    alpha = alpha.expand(dcs_real.size())
    alpha = alpha.to(device)
    
    # compute the interpolate points
    x_interpolates = alpha * dcs_real + ((1 - alpha) * dcs_fake)
    
    # make sure the interpolated points are ready for device
    # and set it to requires_grad=True to track gradients.
    x_interpolates = x_interpolates.to(device)
    x_interpolates = torch.autograd.Variable(x_interpolates, requires_grad=True)
    
    # compute the discriminator prediction of x_interpolates.
    # this is necessary for computing their gradients using torch.autograd
    dsc_interpolates = dsc(x_interpolates)
    
    # now we have the interploated points and the discriminator predictions of them,
    # so we can utilize torch.autograd to compute the gradients for us. 
    gradients = torch.autograd.grad(outputs=dsc_interpolates, inputs=x_interpolates,
                              grad_outputs=torch.ones(dsc_interpolates.size()).to(device),
                              create_graph=True, retain_graph=True, only_inputs=True)[0]
    
    # compute the gradient penalty for K=1,
    # which forces unit gradients.
    # finally, multiply by the regularization parameter 'gamma'.
    K = 1
    gradient_penalty = gamma * ((gradients.norm(2, dim=1) - K) ** 2).mean()
    
    return gradient_penalty