I’m not sure to fully understand what your doing but there is clearly a problem the way you compute the loss before calling backward.
Firstly, you should not try forcing requires_grad or retains_grad, the problem is already there before calling your function array_to_flatten_tensor. In classical situation, you don’t need to set requires_grad on intermediate tensors. Concerning retains_grad, it used when you need to keep the gradients after a backward to accumulate the gradient through different passes for instance, or to compute gradients of gradients, I don’t think you need it too.
To perform the backward pass correctly, you must ensure that all your flow of operations, from the model’s output to the loss, is backward compatible. It’s not the case here. The big issue is that you convert your model output to the float python built-in type, if you want to run the backward pass through your model, you must keep all your intermediate computations on tensors only !
To give a simple example with a L2 loss:
This will work (assuming model is an nn.Module in train mode):
prediction = model(input_tensor)             # here prediction is a tensor with requires_grad = True
loss = ((prediction - label)**2).sum()       # here loss is also a tensor with requires_grad = True, label may or may not be a tensor
loss.backward()                              # backward pass working

This won’t:
prediction = model(input_tensor)             # here prediction is a tensor with requires_grad = True
prediction = float(prediction)               # here prediction is no more a tensor ! We just lost the computational graph
prediction = torch.tensor(prediction)        # here prediction is again a tensor but detached from the computational graph
                                             # so the prediction is no more related to the network output from the backward point of view.
                                             # furthermore now prediction has requires_grad = False
prediction.requires_grad = True              # Forcing requires_grad to be True here won't change anything.
loss = ((prediction - label)**2)
loss.backward()                              # this backward pass will not reach the model !

I invite you to read this guide 1 to understand how backward works.
Hope it helps, good luck with your pytorch journey 
Thomas