I don't think linq is really suitable for this sort of processing - it is mainly useful for performing operations on whole sequences rather than splitting or modifying them. I would do this by accessing the underlying IEnumerator<T> since any method using Take and Skip are going to be quite inefficient.
public static void Batch<T>(this IEnumerable<T> items, int batchSize, Action<IEnumerable<T>> batchAction)
{
    if (batchSize < 1) throw new ArgumentException();
    List<T> buffer = new List<T>();
    using (var enumerator = (items ?? Enumerable.Empty<T>()).GetEnumerator())
    {
        while (enumerator.MoveNext())
        {
            buffer.Add(enumerator.Current);
            if (buffer.Count == batchSize)
            {
                batchAction(buffer);
                buffer.Clear();
            }
        }
        //execute for remaining items
        if (buffer.Count > 0)
        {
            batchAction(buffer);
        }
    }
}