It's very simple.
Do you want to keep the stack trace to see exactly where the exception occurs? Then use throw. This will be like if you don't use catch at all.
Do you only care about the current method's debug information? Then use throw ex.
To demonstrate:
static void Main(string[] args)
{
    try
    {
        Test();
    }
    catch (Exception e)
    {
        Console.WriteLine(e);
    }
}
static void Test()
{
    try
    {
        // long lambda chain
        new Action(() => new Action(() => new Action(() => { throw new InvalidOperationException(); })())())();
    }
    catch (Exception ex)
    {
        //throw;
        //throw ex;
    }
}
throw will keep the stack trace:
System.InvalidOperationException: Operation is not valid due to the current state of the object.
    at ConsoleApplication.Program.<>c.<Test>b__1_2() in ConsoleApplication\Program.cs:line 22
    at ConsoleApplication.Program.<>c.<Test>b__1_1() in ConsoleApplication\Program.cs:line 22
    at ConsoleApplication.Program.<>c.<Test>b__1_0() in ConsoleApplication\Program.cs:line 22
    at ConsoleApplication.Program.Test() in ConsoleApplication\Program.cs:line 26
    at ConsoleApplication.Program.Main(String[] args) in ConsoleApplication\Program.cs:line 13
throw ex will reset stack trace:
System.InvalidOperationException: Operation is not valid due to the current state of the object.
    at ConsoleApplication.Program.Test() in ConsoleApplication\Program.cs:line 27
    at ConsoleApplication.Program.Main(String[] args) in ConsoleApplication\Program.cs:line 13
As for best practices - the choice is usually throw. As a developer, you want to get as much information as you can. throw ex is a counterpart - some information is hidden, but maybe you want to hide it, who knows?