reshapeTo2D() {
    const axis = this.tensor.shape.length - 1
    const axisSize = this.tensor.shape[axis]
    const otherAxes = this.tensor.shape.slice(0, axis)
    const otherAxesSize = otherAxes.reduce((a, b) => a * b, 1)

    const reshaped = ndarray(new this.arrayType(otherAxesSize * axisSize), [otherAxesSize, axisSize])

    const otherAxesData = ndarray(new this.arrayType(otherAxesSize), otherAxes)
    const otherAxesDataRaveled = ndarray(new this.arrayType(otherAxesSize), [otherAxesSize])
    const axisSlices = Array(this.tensor.shape.length).fill(null)
    for (let n = 0; n < axisSize; n++) {
      axisSlices[axis] = n
      ops.assign(otherAxesData, this.tensor.pick(...axisSlices))
      otherAxesDataRaveled.data = otherAxesData.data
      ops.assign(reshaped.pick(null, n), otherAxesDataRaveled)
    }

    this.originalShape = this.tensor.shape
    this.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(this.tensor.shape, false, axis)
    this.tensor = reshaped
    this.is2DReshaped = true
  }
Reshapes data into 2D representation preserving last axis (typically channel axis)