         NDArray::registerSpecialUse({&ctcLosses, &grads}, {&probs});
 
         cudaFree(tempWorkSpace);
-        callCudnnIfNoErr(err, cudnnDestroyTensorDescriptor,probsDesc);
-        if(gradsDesc) callCudnnIfNoErr(err, cudnnDestroyTensorDescriptor,gradsDesc);
-        callCudnnIfNoErr(err, cudnnDestroyCTCLossDescriptor,ctcLossDesc);
         return err;
      }
 

namespace platforms {



    template<typename Op, typename ...Args>
    void callCudnnIfNoErr(cudnnStatus_t &err, Op op, Args&&... args){
        if(err==CUDNN_STATUS_SUCCESS){
            err = op(std::forward<Args>(args)...);
            if(err){
                nd4j_printf("Cudnn error code %s\n",cudnnGetErrorString(err));
            }
        }
    }

    template <typename T>
    const T* bufferInHost( const NDArray &array)  {
        array.syncToHost();
        return reinterpret_cast<const T*>(array.buffer());
    }

    std::vector<int> getConcatTargets(const NDArray &targetLabels, const NDArray &targetLabelLengths){
                //concatenate target labels

        auto logitInputLengths = INPUT_VARIABLE(3);
        auto outputGradients = OUTPUT_VARIABLE(0);
        auto context = block.launchContext();
        REQUIRE_TRUE(outputGradients->isSameShape(logitInput), 0, "CtcLoss Gradient: wrong shape of output array, expected is %s but got %s instead !", ShapeUtils::shapeAsString(logitInput).c_str(), ShapeUtils::shapeAsString(outputGradients).c_str());
        //in Cudnn Batch is in the middle dimension
        logitInput->permutei({1,0,2});
        outputGradients->permutei({1,0,2});
