Interleave two lists of strings
You're right about enumerating both parameters multiple times. Each call to Count or Last will execute the enumerator. This might of course become very inefficient, especially if your collections have a lot of items. 

So what could you do instead? Well, one option would be to replace IEnumerable with the next closest type which is the ICollection. This would guarantee that both collections are already materialized. This however is rarely a good solution so it's preferable to keep it lazy.

But for this, simple LINQ is not enough. You need to work with enumerators directly and implement your extension in such a way that it uses the GetEnumerator method. With it you have the complete control over the enumeration process. With a little bit of logic you can keep you parameters lazy and still be able to validate that the are more values then separators.

You do this by first getting the first value. Then the while will try to get a pair of separators and values to append them to the string. If at some point it could get a separator but not a value, it means that there is at least the same number of separators as values and at this point you can throw an exception. The other case is when there are not enough separators. To detect this you just need to try to get another value after the while. If it works then it means there were not enough separators.

public static string Join(this IEnumerable&lt;string&gt; values, IEnumerable&lt;string&gt; separators)
{
    var result = new StringBuilder();

    using (var value = values.GetEnumerator())
    using (var separator = separators.GetEnumerator())
    {
        if (value.MoveNext())
        {
            result.Append(value.Current);

            while (separator.MoveNext())
            {
                if (value.MoveNext())
                {
                    result
                        .Append(separator.Current)
                        .Append(value.Current);
                }
                else
                {
                    throw new ArgumentException("There are too many separators!");
                }
            }

            if (value.MoveNext())
            {
                throw new ArgumentException("There are not enough separators!");
            }
        }

        return result.ToString();
    }
}


I would also call this extension Join because this is what it does.