Thank you for your suggestions. I did code refactoring and have 2 simple models: with batch_first=True trains and batch_first=False does not train (no errors, just a loss is not decreasing). What can be wrong?
Seems that there is no issue with zero hidden state.
I use CrossEntropyLoss. Target shape is (states_size, 2)
class ModelLSTMFSM_TRAINS(nn.Module):
    def __init__(self, input_size=MAX_STRING_SIZE, hidden_size=256, num_layers=2, states_size=MAX_STATES_SIZE):
        super(ModelLSTMFSM_TRAINS, self).__init__()
        self.states_size = states_size
        self.input_size = input_size
        
        self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True)
        self.fc = nn.Linear(hidden_size, self.states_size * self.states_size * 2)
    
    def forward(self, x):
        x = x.view(x.size(0), -1, self.input_size)
        
        out, _ = self.lstm(x)
        
        out = self.fc(out[:, -1, :])
    
        return out.view(out.size(0), self.states_size, self.states_size, 2)
    
    
class ModelLSTMFSM_NOT_TRAINS(nn.Module):
    def __init__(self, input_size=MAX_STRING_SIZE, hidden_size=256, num_layers=2, states_size=MAX_STATES_SIZE):
        super(ModelLSTMFSM_NOT_TRAINS, self).__init__()
        self.states_size = states_size
        self.input_size = input_size
        
        self.lstm = nn.LSTM(input_size, hidden_size, num_layers)
        self.fc = nn.Linear(hidden_size, self.states_size * self.states_size * 2)
    
    def forward(self, x):
        x = x.view(-1, x.size(0), self.input_size)
        
        out, _ = self.lstm(x)

        out = self.fc(out[-1])
        
        return out.view(out.size(0), self.states_size, self.states_size, 2)