thanks for the reply. I tried wrapping the result of unsqueeze in a var, but that did not work. I checked the recent doc update, and Var is now deprecated, so I simply tried using a new tensor with requires_grad set to true. I still get the same error. Here is what I have:
def i_fgsm(src_img_file, target, model):
toTens = transforms.ToTensor()
PIL_image = pimg.open(src_img_file)
_img = toTens(PIL_image)
_img.unsqueeze_(0) # torch.nn takes only minibatches, so add fake batch dim
img = torch.tensor(_img.numpy(), requires_grad=True)
print (img.shape)

criterion = nn.CrossEntropyLoss()
target_tensor = torch.LongTensor([target])

model.eval()
epsilon = 0.01

for epochs in range(1, 100):
    pred = model(img)
    print ("model pred", pred.max(1)[1])
    loss = criterion(pred, target_tensor)
    loss.backward()

    img = torch.clamp(img + epsilon * torch.sign(img.grad), 0.0, 1.0) # make sure it is a valid image