         in f: @differentiable (Self) -> Tensor<R>
     ) -> (value: Tensor<R>, gradient: TangentVector) {
         let (y, pb) = self.valueWithPullback(in: f)
-        precondition(y.rank == 0)
+        precondition(y.rank == 0, """
+            The function being differentiated produced a tensor with shape \(y.shape). \
+            You can only compute the gradient of functions that return scalar values.
+            """)
         return (y, pb(Tensor<R>(1)))
     }
 

        in f: @differentiable (Self, T) -> Tensor<R>
    ) -> (value: Tensor<R>, gradient: (TangentVector, T.TangentVector)) {
        let (y, pb) = self.valueWithPullback(at: x, in: f)
        precondition(y.rank == 0)
        return (y, pb(Tensor<R>(1)))
    }
}

) -> (value: Tensor<R>, gradient: T.TangentVector)
where T: Differentiable, R: TensorFlowFloatingPoint {
    let (y, pullback) = valueWithPullback(at: x, in: f)
    precondition(y.rank == 0, """
        The function being differentiated produced a tensor with shape \(y.shape). \
        You can only compute the gradient of functions that return scalar values.
        """)
    return (y, pullback(Tensor<R>(1)))
}

