function [Cost,dCostdTheta,RMSE,zList] = ...
    computeBatchCost(Theta,uList,zTargetList, ...
    actFun,gamma,NeuralNoiseStd,actRegWeight,wRegWeight)

%% getting the dimensions of things
hDim=size(Theta,1); 
[uDim,batchSz,numSteps]=size(uList);
zDim = size(zTargetList,1);


%% unpacking theta=[Wrec Win Bin Wout' Bout Wfeedback Wfixation h0]
[Win,Wrec,Bin,Wout,Bout,h0] = unpackTheta(Theta,hDim,uDim,zDim);

%% simulate the network
% initialize h, which is the neural state
h = h0;
actPenalty=0;
SSE=0;
if nargout>3
    zList=zeros(zDim,batchSz,numSteps);
end
% get h trajectory (neural trajectory)
for iStep=1:numSteps
    u=uList(:,:,iStep);
    h = ...
        deadRecNet(h,u,Win,Wrec,Bin, ...
        actFun,gamma,NeuralNoiseStd); % recurrent neural network
    z=Wout*h+Bout;
    if nargout>3
        zList(:,:,iStep)=z;
    end

    % increment SSE
    SSE=SSE+sum((z-zTargetList(:,:,iStep)).^2,"all");

    % increment penalties
    if actRegWeight
        actPenalty=actPenalty+sum(h.^2,"all");
    end
    

end

%% calculate cost and gradient
% get RMSE (performance cost)
RMSE=sqrt(SSE/batchSz/numSteps+1e-7);
% normalize actPenaly
if actPenalty
    actPenalty=actPenalty/batchSz/numSteps/hDim;
end
% get weight penalty (only on input and output weights, like cueva

if wRegWeight
    weightPenalty=mean(Win.^2,"all")+mean(Wout.^2,"all");
else
    weightPenalty=0;
end

% combine all penalties to get the overall cost
Cost = RMSE + actRegWeight*actPenalty +wRegWeight*weightPenalty;



dCostdTheta=dlgradient(Cost,Theta);

end