docs: protected void doTruncatedBPTT(INDArray[] inputs, INDArray[] labels, INDArray[] featureMasks,
                                     INDArray[] labelMasks, LayerWorkspaceMgr workspaceMgr) {
          if (flattenedGradients == null) {
              initGradientsView();
          }
  
          //Approach used here to implement truncated BPTT: if input is 3d, split it. Otherwise: input is unmodified
          long timeSeriesLength = -1;
          for (INDArray in : inputs) {
              if (in.rank() != 3)
                  continue;
              if (timeSeriesLength == -1)
                  timeSeriesLength = in.size(2);
              else if (timeSeriesLength != in.size(2)) {
                  log.warn("Cannot do TBPTT with time series of different lengths");
                  return;
              }
          }
          for (INDArray out : labels) {
              if (out.rank() != 3)
                  continue;
              if (timeSeriesLength == -1)
                  timeSeriesLength = out.size(2);
              else if (timeSeriesLength != out.size(2)) {
                  log.warn("Cannot do TBPTT with time series of different lengths");
                  return;
              }
          }
  
          long fwdLen = configuration.getTbpttFwdLength();
          long nSubsets = timeSeriesLength / fwdLen;
          if (timeSeriesLength % fwdLen != 0)
              nSubsets++;
  
          rnnClearPreviousState();
  
          for (int i = 0; i < nSubsets; i++) {
              long startTimeIdx = i * fwdLen;
              long endTimeIdx = startTimeIdx + fwdLen;
              if (endTimeIdx > timeSeriesLength)
                  endTimeIdx = timeSeriesLength;
  
              // FIXME: int cast
              List<INDArray[]> list = getSubsetsForTbptt((int) startTimeIdx, endTimeIdx, inputs, labels, featureMasks, labelMasks);
  
              setInputs(list.get(0));
              setLabels(list.get(1));
              setLayerMaskArrays(list.get(2), list.get(3));
  
              if (solver == null) {
                  try (MemoryWorkspace wsO = Nd4j.getMemoryManager().scopeOutOfWorkspaces()) {
                      solver = new Solver.Builder().configure(conf()).listeners(getListeners()).model(this)
                              .build();
                  }
              }
              solver.optimize(workspaceMgr);
  
              //Finally, update the state of the RNN layers:
              rnnUpdateStateWithTBPTTState();
          }
  
          if(clearTbpttState) {
              rnnClearPreviousState();
          }
          clearLayerMaskArrays();
      }